Added a little library for reading files structured like inifiles.
authoroliskoli <oliskoli@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 22 Jan 2006 17:04:05 +0000 (17:04 +0000)
committeroliskoli <oliskoli@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 22 Jan 2006 17:04:05 +0000 (17:04 +0000)
gpsbabel/Makefile
gpsbabel/inifile.c [new file with mode: 0644]
gpsbabel/inifile.h [new file with mode: 0644]

index 0a3a86a284aae247afd63eca0ffe91bbe43850d9..774d934a3f22feb768df28101de3c3608b8dd90e 100644 (file)
@@ -68,6 +68,7 @@ SHAPE=shapelib/shpopen.o shapelib/dbfopen.o
 LIBOBJS = queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o \
           csv_util.o strptime.o grtcirc.o vmem.o util_crc.o xmlgeneric.o \
           uuid.o formspec.o xmltag.o cet.o cet_util.o fatal.o rgbcolors.o \
+         inifile \
        $(COLDSYNC) $(GARMIN) $(JEEPS) $(SHAPE) $(FMTS) $(FILTERS)
 OBJS = main.o globals.o $(LIBOBJS)
 
@@ -243,6 +244,7 @@ html.o: html.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \
   jeeps/gpsnmeafmt.h jeeps/gpsnmeaget.h
 igc.o: igc.c defs.h queue.h gbtypes.h
 ignrando.o: ignrando.c defs.h queue.h gbtypes.h xmlgeneric.h
+inifile.o: inifile.c inifile.h defs.h queue.h gbtypes.h
 internal_styles.o: internal_styles.c defs.h queue.h gbtypes.h
 kml.o: kml.c defs.h queue.h gbtypes.h xmlgeneric.h
 lowranceusr.o: lowranceusr.c defs.h queue.h gbtypes.h
diff --git a/gpsbabel/inifile.c b/gpsbabel/inifile.c
new file mode 100644 (file)
index 0000000..4eb0aa7
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+    Library for inifile like data files.
+    
+    Copyright (C) 2006 Olaf Klein, o.b.klein@t-online.de
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "defs.h"
+#include "inifile.h"
+
+#define MYNAME "inifile"
+
+typedef struct inifile_entry_s
+{
+       queue Q;
+       char *key;
+       char *val;
+} inifile_entry_t;
+
+typedef struct inifile_section_s
+{
+       queue Q;
+       char *name;
+       int ientries;
+       queue entries;
+} inifile_section_t;
+
+/* internal procedures */
+
+#define START_BUFSIZE 257
+#define DELTA_BUFSIZE 128
+
+static void
+inifile_load_file(FILE *fin, inifile_t *inifile, const char *myname)
+{
+       char *buf;
+       size_t bufsize = START_BUFSIZE;
+       inifile_section_t *sec = NULL;
+
+       buf = xmalloc(bufsize);
+       
+       while ((fgets(buf, bufsize, fin)))
+       {
+               char *cin;
+       
+               while (strchr(buf, '\n') == NULL)
+               {
+                       buf = xrealloc(buf, bufsize + DELTA_BUFSIZE);
+                       cin = fgets(buf + bufsize - 1, DELTA_BUFSIZE + 1, fin);
+                       bufsize+=DELTA_BUFSIZE;
+                       if (cin == NULL) break;
+               }
+               
+               cin = lrtrim(buf);
+               if (*cin == '\0') continue;
+               
+               if (*cin == '[')
+               {
+                       
+                       char *cend = strchr(++cin, ']');
+
+                       if (cend != NULL)
+                       {
+                               *cend = '\0';
+                               cin = lrtrim(cin);
+                       }
+                       if ((*cin == '\0') || (cend == NULL))
+                               fatal("%s: invalid section header!\n", myname);
+                               
+                       sec = xcalloc(1, sizeof(*sec));
+                       
+                       sec->name = xstrdup(cin);
+                       QUEUE_INIT(&sec->entries);
+                       ENQUEUE_TAIL(&inifile->secs, &sec->Q);
+                       inifile->isecs++;
+               }
+               else
+               {
+                       char *cx;
+                       inifile_entry_t *entry;
+                       
+                       if (sec == NULL)
+                               fatal("%s: missing section header!\n", myname);
+                       
+                       entry = xcalloc(1, sizeof(*entry));
+                       ENQUEUE_TAIL(&sec->entries, &entry->Q);
+                       sec->ientries++;
+                       
+                       cx = strchr(cin, '=');
+                       if (cx != NULL)
+                       {
+                               *cx = '\0';
+                               cin = lrtrim(cin);
+                       }
+                       
+                       entry->key = xstrdup(cin);
+                       
+                       if (cx != NULL)
+                       {
+                               cx = lrtrim(++cx);
+                               entry->val = xstrdup(cx);
+                       }
+                       else
+                               entry->val = xstrdup("");
+               }
+       }
+       xfree(buf);
+}
+
+static char *
+inifile_find_value(const inifile_t *inifile, const char *sec_name, const char *key)
+{
+       queue *elem, *tmp;
+       
+       QUEUE_FOR_EACH(&inifile->secs, elem, tmp)
+       {
+               inifile_section_t *sec = (inifile_section_t *) elem;
+               
+               if (case_ignore_strcmp(sec->name, sec_name) == 0)
+               {
+                       queue *elem, *tmp;
+                       
+                       QUEUE_FOR_EACH(&sec->entries, elem, tmp)
+                       {
+                               inifile_entry_t *entry = (inifile_entry_t *) elem;
+                       
+                               if (case_ignore_strcmp(entry->key, key) == 0)
+                               {
+                                       return entry->val;
+                               }
+                       }
+               }
+       }
+       return NULL;
+}
+
+/* public procedures */
+
+/*
+       inifile_init:
+         reads inifile filename into memory
+         myname represents the calling module
+ */
+inifile_t *
+inifile_init(const char *filename, const char *myname)
+{
+       inifile_t *result;
+       FILE *fin;
+       
+       fin = xfopen(filename, "r", myname);
+       
+       result = xcalloc(1, sizeof(*result));
+       QUEUE_INIT(&result->secs);
+       inifile_load_file(fin, result, myname);
+       
+       fclose(fin);
+       return result;
+}
+
+void
+inifile_done(inifile_t *inifile)
+{
+       if (inifile == NULL) return;
+       
+       if (inifile->isecs > 0) 
+       {
+               queue *elem, *tmp;
+               
+               QUEUE_FOR_EACH(&inifile->secs, elem, tmp) {
+                       inifile_section_t *sec = (inifile_section_t *) elem;
+                       
+                       if (sec->ientries > 0) {
+                               queue *elem, *tmp;
+                               
+                               QUEUE_FOR_EACH(&sec->entries, elem, tmp) {
+                                       inifile_entry_t *entry = (inifile_entry_t *) elem;
+                                       
+                                       if (entry->key) xfree(entry->key);
+                                       if (entry->val) xfree(entry->val);
+                                       dequeue(elem);
+                                       xfree(entry);
+                               }
+                       }
+                       dequeue(elem);
+                       if (sec->name) xfree(sec->name);
+                       xfree(sec);
+               }
+               xfree(inifile);
+       }
+}
+
+int 
+inifile_has_section(const inifile_t *inifile, const char *section)
+{
+       queue *elem, *tmp;
+       
+       QUEUE_FOR_EACH(&inifile->secs, elem, tmp)
+       {
+               inifile_section_t *sec = (inifile_section_t *) elem;
+               if (case_ignore_strcmp(sec->name, section) == 0)
+                       return 1;
+       }
+       return 0;
+}
+
+/* 
+     inifile_readstr:
+       returns NULL if not found, otherwise a pointer to the value of key ...
+       all key values are valid entities until "inifile_done" 
+ */
+
+char *
+inifile_readstr(const inifile_t *inifile, const char *section, const char *key)
+{
+       return inifile_find_value(inifile, section, key);
+}
+
+/* 
+     inifile_readint:
+       on success the value is stored into "*value" and "inifile_readint" returns 1,
+       otherwise inifile_readint returns 0
+ */
+int 
+inifile_readint(const inifile_t *inifile, const char *section, const char *key, int *value)
+{
+       char *str;
+       
+       str = inifile_find_value(inifile, section, key);
+       
+       if (str == NULL) {
+               return 0;
+       }
+       
+       if (value != NULL) {
+               *value = atoi(str);
+       }
+       return 1;
+}
+
+/*
+     inifile_readint_def:
+       if found inifile_readint_def returns value of key, otherwise a default value "def"
+ */
+
+int 
+inifile_readint_def(const inifile_t *inifile, const char *section, const char *key, const int def)
+{
+       int result;
+       
+       if (inifile_readint(inifile, section, key, &result) == 0) {
+               return def;
+       }
+       else {
+               return result;
+       }
+}
diff --git a/gpsbabel/inifile.h b/gpsbabel/inifile.h
new file mode 100644 (file)
index 0000000..077c3ec
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+    Library for inifile like data files.
+
+    Copyright (C) 2006 Olaf Klein, o.b.klein@t-online.de
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+*/
+
+#ifndef HAVE_INIFILE_H
+#define HAVE_INIFILE_H
+
+#include "defs.h"
+
+typedef struct inifile_s
+{
+       int isecs;                      /* number of sections */
+       queue secs;                     /* sections */
+} inifile_t;
+
+/*
+       inifile_init:
+         reads inifile filename into memory
+         myname represents the calling module
+ */
+inifile_t * inifile_init(const char *filename, const char *myname);
+void inifile_done(inifile_t *inifile);
+
+int inifile_has_section(const inifile_t *inifile, const char *section);
+
+/* 
+     inifile_readstr:
+       returns NULL if not found, otherwise a pointer to the value of key ...
+       all key values are valid entities until "inifile_done" 
+ */
+char *inifile_readstr(const inifile_t *inifile, const char *section, const char *key);
+
+/* 
+     inifile_readint:
+       on success the value is stored into "*value" and "inifile_readint" returns 1,
+       otherwise inifile_readint returns 0
+ */
+int inifile_readint(const inifile_t *inifile, const char *section, const char *key, int *value);
+
+/*
+     inifile_readint_def:
+       if found inifile_readint_def returns value of key, otherwise a default value "def"
+ */
+int inifile_readint_def(const inifile_t *inifile, const char *section, const char *key, const int def);
+
+#endif